//==========================================================================
// Copyright (c) 2000-2009,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "CGrafixObjectEnumerator.h"
#include "_CGrafixObjectEnumerator.cpp"

ECode CGrafixObjectEnumerator::Initialize(
    /* [in] */ Handle32 appletId,
    /* [in] */ CGrafixEngine * pEngine)
{
    assert(pEngine);

    pEngine->AddRef();
    m_engine = pEngine;

    if (!m_engine->m_stack) {
        GFX_EXPRESSION(ERRORLEVEL,
            kprintf("The stack doesn't be initialized\n"));

        return E_STACK_NOT_INITIALIZE;
    }

    g_lock.Lock();

    m_grafixObjects = &m_engine->m_stack->m_windows;
    m_changed = &m_engine->m_stack->m_grafixObjectStackChanged;

    m_current = m_grafixObjects->count;

    m_appletId = appletId;

    Reset();

    g_lock.Unlock();

    return NOERROR;
}

CGrafixObjectEnumerator::~CGrafixObjectEnumerator()
{
    if (m_engine) {
        m_engine->Release();
    }
}

ECode CGrafixObjectEnumerator::Current(
    /* [out] */ PInterface * ppObject)
{
    IGrafixObject * grafixObject;
    ECode ec = NOERROR;

    if (!ppObject) {
        GFX_EXPRESSION(ERRORLEVEL,
            kprintf("Invalid argument\n"));

        return E_INVALID_ARGUMENT;
    }

    g_lock.Lock();

    if (*m_changed) {
        GFX_EXPRESSION(ERRORLEVEL,
            kprintf("The grafixObjects be changed\n"));
        ec = E_INVALID_OPERATION;

        goto Exit;
    }

    if (m_grafixObjects->count == m_current) {
        GFX_EXPRESSION(ERRORLEVEL,
            kprintf("Be must movenext to the first element\n"));
        ec = E_INVALID_OPERATION;

        goto Exit;
    }

    if (-1 == m_current) {
        GFX_EXPRESSION(ERRORLEVEL,
            kprintf("Be must reset and movenext\n"));
        ec = E_INVALID_OPERATION;

        goto Exit;
    }

    assert(m_current >= 0 && m_current < m_grafixObjects->count);
    grafixObject = (IGrafixObject *)FusionVectorAt(m_grafixObjects, m_current);
    grafixObject->AddRef();
    *ppObject = grafixObject;

Exit:
    g_lock.Unlock();

    return ec;
}

ECode CGrafixObjectEnumerator::MoveNext(
    /* [out] */ Boolean * pSucceeded)
{
    if (!pSucceeded) {
        GFX_EXPRESSION(ERRORLEVEL,
            kprintf("Invalid argument\n"));

        return E_INVALID_ARGUMENT;
    }

    ECode   ec = NOERROR;

    g_lock.Lock();

    if (*m_changed) {
        GFX_EXPRESSION(ERRORLEVEL,
            kprintf("The grafixObjects be changed\n"));
        ec = E_INVALID_OPERATION;

        goto Exit;
    }

    if (-1 == m_grafixObjects->count) {
        GFX_EXPRESSION(ERRORLEVEL,
            kprintf("The current position have be out of the last element\n"));
        ec = E_INVALID_OPERATION;

        goto Exit;
    }

    do {
        m_current--;

        if (-1 == m_appletId || -1 == m_current) {
            break;
        }

        CGrafixObject* grafixObject = (CGrafixObject *)FusionVectorAt(m_grafixObjects, m_current);
        if (grafixObject->m_appletId == m_appletId) {
            break;
        }
    } while (TRUE);

    assert(m_current >= -1 && m_current < m_grafixObjects->count);

    if (m_current == -1) {
        *pSucceeded = FALSE;
    }
    else {
        *pSucceeded = TRUE;
    }

Exit:
    g_lock.Unlock();

    return ec;
}

ECode CGrafixObjectEnumerator::Reset()
{
    g_lock.Lock();

    *m_changed = FALSE;
    m_current = m_grafixObjects->count;

    g_lock.Unlock();

    return NOERROR;
}

